package com.edu.app.util.alioss;


import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.sf.json.JSONObject;

import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Aliyun OSS
 * 2016-1-20 15:10:21
 * @author Jecced
 */
public class OssAccessor {
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private String ossEndpoint;
    private int timeout;

    private OSSClient ossClient;

    public OssAccessor() {}

    /**
     * OSS初始化
     */
    public void init() {
        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(timeout);
        conf.setMaxErrorRetry(10);
        ossClient = new OSSClient("http://" + ossEndpoint, accessKeyId, accessKeySecret, conf);
        System.out.println("OSS初始化");
    }

    public void destroy(){
        ossClient.shutdown();
    }

    /**
     * 指定的key是否存在
     */
    public boolean isExist(String key){
        key = genKey(key);
        return ossClient.doesObjectExist(bucketName, key);
    }

    /**
     * 从OSS中获取文件输入流
     */
    public InputStream getObjeInputStream(String key){
        key = genKey(key);
        OSSObject obj = ossClient.getObject(bucketName, key);
        return obj.getObjectContent();
    }

    /**
     * 将输入流下载存到指定的File文件中
     */
    public void saveIsToFile(InputStream is ,File file){
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024 * 10];
            int len = -1;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.safeClose(fos);
        }
    }



    /**
     * 文件下载,以流的形式
     */
    public void downObj(String key,File file){
        key = genKey(key);
        InputStream is = getObjeInputStream(key);
        saveIsToFile(is, file);
    }

    /**
     * 简单上传OSS文件
     * @param name	文件名
     * @param file	File对象
     * @param path	存储路径
     * @param contentType	手动设置文件类型：image/png
     * @return OSS文件Key的路径
     */
    public String uploadObj(String path, String name, File file,String contentType) {
        String key = path + "/" + name;
        key = genKey(key);
        ObjectMetadata meta = null;
        if(contentType != null){
            meta = new ObjectMetadata();
            meta.setContentType(contentType);
        }
        ossClient.putObject(bucketName, key, file, meta);
        Date expiration = new Date(new Date().getTime() + 3600 * 1000);
// 生成URL。
        //ossClient.setBucketAcl("<yourBucketName>", CannedAccessControlList.Private);
        //URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
        return "http://" + bucketName + "." + ossEndpoint + "/" + key;
        //return url.toString();
    }

    public String uploadObj(String path, String name, File file) {
        return uploadObj(path,name,file,null);
    }

    /**
     * 删除指定key
     */
    public void delObj(String key){
        ossClient.deleteObject(bucketName, key);
    }

    /**
     * 处理key开头是/,返回开头没有/的key
     */
    private String genKey(String key){
        if (key != null) {
            key = key.replaceAll("\\\\", "/");
        }
        while (key != null && key.startsWith("/")) {
            key = key.substring(1, key.length());
        }
        return key;
    }

    public OSSClient getOSSClient() {
        return ossClient;
    }

    public void setAccessKeyId(String accessKeyId) {
        this.accessKeyId = accessKeyId;
    }

    public void setAccessKeySecret(String accessKeySecret) {
        this.accessKeySecret = accessKeySecret;
    }

    public void setOssBucket(String ossBucket) {
        this.bucketName = ossBucket;
    }

    public void setOssEndpoint(String ossEndpoint) {
        this.ossEndpoint = ossEndpoint;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public   Map<String,String> assumeRole(String accessKeyId,
                                            String accessKeySecret,
                                            String roleArn,
                                            String roleSessionName,
                                            String policy,
                                            ProtocolType protocolType,
                                            long durationSeconds)
            throws ClientException
    {
        Map<String, String> respMap = null;
        try {
            // 创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
            IClientProfile profile = DefaultProfile.getProfile(OssConfig.REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
            DefaultAcsClient client  = new DefaultAcsClient(profile);

            // 创建一个 AssumeRoleRequest 并设置请求参数
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setVersion(OssConfig.STS_API_VERSION);
            request.setMethod(MethodType.POST);
            request.setProtocol(protocolType);

            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy);
            request.setDurationSeconds(durationSeconds);

            // 发起请求，并得到response
            final AssumeRoleResponse response = client.getAcsResponse(request);

            respMap = new LinkedHashMap<String, String>();
            JSONObject returnData = new JSONObject();
            respMap.put("expiration", response.getCredentials().getExpiration());
            respMap.put("accessKeyId", response.getCredentials().getAccessKeyId());
            respMap.put("accessKeySecret", response.getCredentials().getAccessKeySecret());
            respMap.put("securityToken", response.getCredentials().getSecurityToken());

        } catch (ClientException e) {
            throw e;
        }
        return respMap;
    }

    public   Map<String,String> getPostObjectPolicy(
                                                     String bucket,
                                                     String endpoint,
                                                     String accessId,
                                                     String accessKey,
                                                     String callbackUrl,
                                                     Integer tenant_id)
            throws UnsupportedEncodingException
    {


        String dir = "user-dir";
        String host = "http://" + bucket + "." + endpoint;

        Map<String, String> respMap = null;


        Map<String,String> callbackParamMap = new HashMap<String,String>();
        callbackParamMap .put( "callbackUrl",callbackUrl);
        //callbackParamMap.put("callbackBody","{\"bucket\":${bucket},\"filename\":${object},\"etag\":${etag},\"size\":${size},\"mimeType\":${mimeType},\"height\":${imageInfo.height},\"width\":${imageInfo.width}}");
        callbackParamMap.put("callbackBody","{\"bucket\":${bucket},\"filename\":${object},\"etag\":${etag},\"size\":${size},\"mimeType\":${mimeType}, \"tenant_id\": " + tenant_id + "}");
        callbackParamMap.put("callbackBodyType", "application/json");
        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
        String callback = gson.toJson(callbackParamMap);

        String base64Callback = BinaryUtil.toBase64String(callback.getBytes("UTF-8"));

        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            java.sql.Date expiration    = new java.sql.Date(expireEndTime);

            PolicyConditions policyConds   = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy    = ossClient.generatePostPolicy(expiration, policyConds);

            byte[] binaryData    = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);

            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            respMap.put("callback",base64Callback);


        } catch (UnsupportedEncodingException e) {
            throw e;
        }
        return respMap;
    }

    public String geturl(String ObjectName) {
        return "http://" + bucketName + "." + ossEndpoint + "/" + ObjectName;
    }
}